#include <windows.h>
#include "CDXTexture2D.h"
#include "CReleaseMacro.h"
#include <atlcomcli.h>
#include <assert.h>
//////////Texture Base////////////
CDXTexture2D::CDXTexture2D(CDXDevice* pDevice) : CDXResource(pDevice)
{
	m_pTexture = NULL;
	m_pReadAgentTexture = NULL;
	m_pWriteAgentTexture = NULL;

}
CDXTexture2D::~CDXTexture2D()
{
	ReleaseResources();
}
HRESULT CDXTexture2D::ReleaseResources()
{
	SAFE_RELEASE(m_pTexture);
	SAFE_RELEASE(m_pReadAgentTexture);
	SAFE_RELEASE(m_pWriteAgentTexture);
	
	return __super::ReleaseResources();
}

ID3D11Texture2D* CDXTexture2D::GetD3D11Texture2D() const
{
	return m_pTexture;
}

HRESULT CDXTexture2D::GetDC(BOOL discard, HDC* hdc)
{
	if (m_pTexture == NULL || hdc == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	IDXGISurface1* pDXGISurface = NULL;
	hr = GetDXGISurface11(&pDXGISurface);
	if (FAILED(hr))
		return hr;
	hr = pDXGISurface->GetDC(discard, hdc);
	return hr;
}
HRESULT CDXTexture2D::ReleaseDC(RECT* pDirtyRect)
{
	if (m_pTexture == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	IDXGISurface1* pDXGISurface = NULL;
	hr = GetDXGISurface11(&pDXGISurface);
	if (FAILED(hr))
		return hr;
	hr = pDXGISurface->ReleaseDC(pDirtyRect);
	return hr;
}

HRESULT CDXTexture2D::Create(D3D11_TEXTURE2D_DESC* pDesc, D3D11_SUBRESOURCE_DATA* pInitData)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	ReleaseResources();

	HRESULT hr = S_OK;	
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	hr = pDX11Device->CreateTexture2D( pDesc, pInitData, &m_pTexture );
	return hr;
}

HRESULT CDXTexture2D::GetRawDataInfo(unsigned long& nImgBufSize, unsigned long& nImgBufStride, UINT& nDepth, UINT& nChannel)
{
	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC desc;
	m_pTexture->GetDesc(&desc);
	nImgBufSize = 0;
	nImgBufStride = 0;
	UINT nBits = 0;
	BOOL bAvgBits = TRUE;
	hr = CDXDevice::GetDXGIFormatNumBits(desc.Format, nBits);
	if (FAILED(hr))
		return hr;
	hr = CDXDevice::GetDXGIFormatNumChannel(desc.Format, nChannel, bAvgBits);
	if (FAILED(hr))
		return hr;
	if (bAvgBits == FALSE)
	{
		return E_FAIL;
	}

	nImgBufSize = desc.Width*desc.Height*nBits/8;
	nImgBufStride = desc.Width*nBits/8;
	nDepth = nBits/nChannel;

	return S_OK;
}
HRESULT CDXTexture2D::GetRawData(void* pBuf)
{
	if (m_pTexture == NULL || m_pDevice == NULL || pBuf == NULL)
		return E_FAIL;

	

	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();
	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC desc;
	m_pTexture->GetDesc(&desc);

	unsigned long nImgBufSize;
	unsigned long nImgBufStride;
	UINT nDepth;
	UINT nChannel;
	hr = GetRawDataInfo(nImgBufSize, nImgBufStride, nDepth, nChannel);
	if (FAILED(hr))
		return hr;

	ID3D11Texture2D* pCloneTexture = NULL;
	if (desc.Usage == D3D11_USAGE_STAGING)
	{
		pCloneTexture = m_pTexture;
		pCloneTexture->AddRef();
	}
	else
	{
		if (m_pReadAgentTexture == NULL)
		{
			desc.BindFlags = 0;
			desc.Usage = D3D11_USAGE_STAGING;
			desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
			desc.MiscFlags = 0;
			hr = pDX11Device->CreateTexture2D(&desc, NULL, &m_pReadAgentTexture);
			if (FAILED(hr))
				return E_FAIL;
		}
		pCloneTexture = m_pReadAgentTexture;
		pCloneTexture->AddRef();
	}
	
	if (pCloneTexture != m_pTexture)
	{
		hr = KeyMutex11Acquire();
		pDeviceContext->CopyResource(pCloneTexture, m_pTexture);
		hr = KeyMutex11Release();
	}
	D3D11_MAPPED_SUBRESOURCE mappedData;
	hr = KeyMutex11Acquire();
	hr = pDeviceContext->Map(pCloneTexture, 0, D3D11_MAP_READ, 0, &mappedData);
	if (FAILED(hr))
	{
		SAFE_RELEASE(pCloneTexture);
		hr = KeyMutex11Release();
		return E_FAIL;
	}
	for (UINT y = 0; y < desc.Height; y++)
	{
		BYTE* pImgBuf = (BYTE*)pBuf;
		BYTE* pTexBuf = (BYTE*)mappedData.pData;
		memcpy(&pImgBuf[y*nImgBufStride], &pTexBuf[y*mappedData.RowPitch], nImgBufStride);
	}
	pDeviceContext->Unmap(pCloneTexture, 0);
	SAFE_RELEASE(pCloneTexture);
	hr = KeyMutex11Release();
	return S_OK;
}

HRESULT CDXTexture2D::SetRawData(void* pBuf, unsigned long nImgBufSize, unsigned long nImgBufStride, UINT nDepth, UINT nChannel)
{
	if (m_pTexture == NULL || m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC desc;
	m_pTexture->GetDesc(&desc);
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();

	unsigned long nTexBufSize = 0;
	unsigned long nTexBufStride = 0;
	UINT nBits = 0;
	UINT nTexChannel = 0;
	BOOL bAvgBits = TRUE;
	hr = CDXDevice::GetDXGIFormatNumBits(desc.Format, nBits);
	if (FAILED(hr))
		return hr;
	hr = CDXDevice::GetDXGIFormatNumChannel(desc.Format, nTexChannel, bAvgBits);
	if (FAILED(hr))
		return hr;
	if (bAvgBits == FALSE)
	{
		return E_FAIL;
	}

	nTexBufSize = desc.Width*desc.Height*nBits/8;
	nTexBufStride = desc.Width*nBits/8;
	UINT nTexDepth = nBits/nChannel;

	if (nImgBufSize != nTexBufSize || nImgBufStride != nTexBufStride || nDepth != nTexDepth || nChannel != nTexChannel)
	{
		return E_INVALIDARG;
	}

	ID3D11Texture2D* pCloneTexture = NULL;
	if (desc.Usage == D3D11_USAGE_DYNAMIC)
	{
		pCloneTexture = m_pTexture;
		pCloneTexture->AddRef();
	}
	else
	{
		if (m_pWriteAgentTexture == NULL)
		{
			desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
			desc.Usage = D3D11_USAGE_DYNAMIC;
			desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
			desc.MiscFlags = 0;
			hr = pDX11Device->CreateTexture2D(&desc, NULL, &m_pWriteAgentTexture);
			if (FAILED(hr))
				return E_FAIL;
		}
		pCloneTexture = m_pWriteAgentTexture;
		pCloneTexture->AddRef();
	}


	D3D11_MAPPED_SUBRESOURCE mappedData; 
	hr = pDeviceContext->Map(pCloneTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedData);
	if (FAILED(hr))
	{
		SAFE_RELEASE(pCloneTexture);
		return E_FAIL;
	}
	for (UINT y = 0; y < desc.Height; y++)
	{
		BYTE* pImgBuf = (BYTE*)pBuf;
		BYTE* pTexBuf = (BYTE*)mappedData.pData;
		memcpy(&pTexBuf[y*mappedData.RowPitch], &pImgBuf[y*nImgBufStride], nImgBufStride);
	}

	pDeviceContext->Unmap(pCloneTexture, 0);

	if (pCloneTexture != m_pTexture)
	{
		pDeviceContext->CopyResource(m_pTexture, pCloneTexture);
	}

	SAFE_RELEASE(pCloneTexture);
	return S_OK;
}


HRESULT CDXTexture2D::OpenShareHandle(HANDLE hResource)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	if (hResource == 0)
		return E_INVALIDARG;
	if (hResource == m_hShareHandle)
	{
		return S_OK;
	}
	HRESULT hr = S_OK;
	hr = ReleaseResources();
	CComPtr<ID3D11Resource> pResource = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	hr = pDX11Device->OpenSharedResource(hResource, __uuidof(ID3D11Resource), (void**)(&pResource)); 
	if (FAILED(hr))
		return hr;
	hr = pResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&m_pTexture)); 
	if (FAILED(hr))
		return hr; 
	m_hShareHandle = hResource;
	return S_OK;
}
HRESULT CDXTexture2D::SaveToFile(LPCWSTR path)
{
	HRESULT hr = S_OK;
	if (m_pTexture == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	void* pRawData = NULL;
	unsigned long nRawDataSize = 0;
	unsigned long nRawDataStride = 0;
	UINT nDepth = 0;
	UINT nChannel = 0;
	hr = GetRawDataInfo(nRawDataSize,  nRawDataStride,  nDepth, nChannel);
	if (FAILED(hr))
		return hr;
	pRawData = new BYTE[nRawDataSize];
	hr = GetRawData(pRawData);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	IWICImagingFactory* pWICFactory = NULL;
	hr = m_pDevice->GetWICFactory(&pWICFactory);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return E_FAIL;
	}
	D3D11_TEXTURE2D_DESC texDesc;
	m_pTexture->GetDesc(&texDesc);
	GUID wicFmt;
	hr = CDXDevice::GetWICFmtFromDXGIFmt(texDesc.Format, &wicFmt);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	UINT cbPixel = nChannel;

	UINT cbStride = nRawDataStride; 
	UINT cbBufferSize = nRawDataSize;

	CComPtr<IWICBitmap> pWICBitmap = NULL;
	hr = pWICFactory->CreateBitmapFromMemory(texDesc.Width, texDesc.Height, wicFmt, 
		cbStride, cbBufferSize, (BYTE*)pRawData, &pWICBitmap);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;	
	}
	CComPtr<IWICStream> pStream = NULL;
	hr = pWICFactory->CreateStream(&pStream);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	WCHAR mPath[MAX_PATH] = {0};
	WCHAR fExt[MAX_PATH] = {0};
	const WCHAR* tmpfExt = wcsrchr(path, L'.');
	GUID containerFmt;
	if (tmpfExt == NULL)
	{
		swprintf_s(fExt, MAX_PATH, L"png");
		swprintf_s(mPath, MAX_PATH, L"%s.%s", path, fExt);
		_wcslwr_s(fExt, MAX_PATH);
		_wcslwr_s(mPath, MAX_PATH);

	}
	else
	{
		wcscpy_s(fExt, MAX_PATH, &(tmpfExt[1]));
		wcscpy_s(mPath, MAX_PATH, path);
		_wcslwr_s(fExt, MAX_PATH);
		_wcslwr_s(mPath, MAX_PATH);
	}
	if (wcscmp(fExt, L"png") == 0)
	{
		containerFmt = GUID_ContainerFormatPng;
	}
	else if (wcscmp(fExt, L"ico") == 0)
	{
		containerFmt = GUID_ContainerFormatIco;
	}
	else if (wcscmp(fExt, L"jpg") == 0)
	{
		containerFmt = GUID_ContainerFormatJpeg;
	}
	else if (wcscmp(fExt, L"tif") == 0)
	{
		containerFmt = GUID_ContainerFormatTiff;
	}
	else if (wcscmp(fExt, L"gif") == 0)
	{
		containerFmt = GUID_ContainerFormatGif;
	}
	else if (wcscmp(fExt, L"wmp") == 0)
	{
		containerFmt = GUID_ContainerFormatWmp;
	}
	else if (wcscmp(fExt, L"dds") == 0)
	{
		hr = D3DX11SaveTextureToFile(pContext, m_pTexture, D3DX11_IFF_DDS, mPath);
		return hr;
	}
	else
	{
		return E_FAIL;
	}

	hr = pStream->InitializeFromFilename(mPath, GENERIC_WRITE);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	CComPtr<IWICBitmapEncoder> pEncoder = NULL;
	hr = pWICFactory->CreateEncoder(containerFmt, NULL, &pEncoder);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	CComPtr<IWICBitmapFrameEncode> pFrameEncode = NULL;
	hr = pEncoder->CreateNewFrame(&pFrameEncode, NULL);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	hr = pFrameEncode->Initialize(NULL);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return E_FAIL;
	}
	hr = pFrameEncode->SetSize(texDesc.Width, texDesc.Height);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	hr = pFrameEncode->SetPixelFormat(&wicFmt);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	hr = pFrameEncode->WriteSource(pWICBitmap, NULL);

	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	hr = pFrameEncode->Commit();

	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pRawData);
		return hr;
	}
	hr = pEncoder->Commit();
	SAFE_DELETE_ARRAY(pRawData);
	return hr;
	
}

HRESULT CDXTexture2D::LoadFromFile(LPCWSTR path, D3DX11_IMAGE_LOAD_INFO* pImageInfo)
{
	if (m_pDevice == NULL)
		return E_FAIL;

	HRESULT hr = S_OK;
	hr = ReleaseResources();
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	D3DX11_IMAGE_LOAD_INFO loadImgInfo;
	if (pImageInfo != NULL)
	{
		loadImgInfo = *pImageInfo;
	}
	else
	{
		loadImgInfo.Width = D3DX11_DEFAULT;
		loadImgInfo.Height = D3DX11_DEFAULT;
		loadImgInfo.Depth = D3DX11_DEFAULT;
		loadImgInfo.FirstMipLevel = D3DX11_DEFAULT;
		loadImgInfo.MipLevels = 1;
		loadImgInfo.Usage = D3D11_USAGE_DEFAULT;
		loadImgInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE;
		loadImgInfo.CpuAccessFlags = 0;
		loadImgInfo.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
		loadImgInfo.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
		loadImgInfo.Filter = D3DX11_DEFAULT;
		loadImgInfo.MipFilter = D3DX11_DEFAULT;
		loadImgInfo.pSrcInfo = NULL;	
	}
	ID3D11Texture2D* pTmpTexture = NULL;
	hr = D3DX11CreateTextureFromFile(pDX11Device, path, &loadImgInfo, NULL, (ID3D11Resource**)&pTmpTexture, NULL);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	// if we set D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX, the D3DX11CreateTextureFromFile will failed, so...
	D3D11_TEXTURE2D_DESC desc;
	pTmpTexture->GetDesc(&desc);
	desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
	hr = Create(&desc, NULL);
	if (FAILED(hr))
	{
		assert(0);
		SAFE_RELEASE(pTmpTexture);
		return hr;
	}
	KeyMutex11Acquire();
	pContext->CopyResource(m_pTexture, pTmpTexture);
	KeyMutex11Release();
	SAFE_RELEASE(pTmpTexture);
	return hr;
}


HRESULT CDXTexture2D::Resize(UINT width, UINT height)
{
	if (m_pTexture == NULL || m_pDevice == NULL )
		return E_FAIL;
	if (width <=0 || height <= 0)
		return E_FAIL;

	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC oldDesc;
	m_pTexture->GetDesc(&oldDesc);
	if (oldDesc.Width == width && oldDesc.Height == height)
		return S_OK;
	D3D11_TEXTURE2D_DESC newDesc = oldDesc;
	newDesc.Width = width;
	newDesc.Height = height;
	ID3D11Texture2D *pTexture = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();
	hr = pDX11Device->CreateTexture2D( &newDesc, NULL, &pTexture);
	if (FAILED(hr))
		return hr;

	hr = D3DX11LoadTextureFromTexture(pDeviceContext, m_pTexture, NULL, pTexture);
	if (FAILED(hr))
		return hr;
	ReleaseResources();
	m_pTexture = pTexture;

	return hr;
}
HRESULT CDXTexture2D::ResetFormat(DXGI_FORMAT fmt)
{
	if (m_pTexture == NULL || m_pDevice == NULL )
		return E_FAIL;

	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC oldDesc;
	m_pTexture->GetDesc(&oldDesc);
	if (oldDesc.Format == fmt)
		return S_OK;
	D3D11_TEXTURE2D_DESC newDesc = oldDesc;
	newDesc.Format = fmt;
	ID3D11Texture2D *pTexture = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();
	hr = pDX11Device->CreateTexture2D( &newDesc, NULL, &pTexture);
	if (FAILED(hr))
		return hr;

	hr = D3DX11LoadTextureFromTexture(pDeviceContext, m_pTexture, NULL, pTexture);
	if (FAILED(hr))
		return hr;
	ReleaseResources();
	m_pTexture = pTexture;
	return S_OK;
}

HRESULT CDXTexture2D::GetFrameSize(UINT* width, UINT* height)
{
	if (width == NULL || height == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	D3D11_TEXTURE2D_DESC desc;
	this->GetDesc(&desc);
	*width = desc.Width;
	*height = desc.Height;
	return S_OK;
}

ID3D11Resource* CDXTexture2D::GetResource() const
{
	return (ID3D11Resource*)m_pTexture;
}

HRESULT CDXTexture2D::GetDesc(D3D11_TEXTURE2D_DESC* pDesc)
{
	if (m_pTexture == NULL || pDesc == NULL)
		return E_FAIL;
	m_pTexture->GetDesc(pDesc);
	return S_OK;
}

HRESULT CDXTexture2D::CopyFrom(CDXTexture2D* pCDXTexture)
{
	if (pCDXTexture == NULL || m_pDevice == NULL)
		return E_INVALIDARG;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	CAutoLock lck1(this);
	CAutoLock lck2(pCDXTexture);

	ID3D11Texture2D* pDestTex = this->GetD3D11Texture2D();
	ID3D11Texture2D* pSrcTex = pCDXTexture->GetD3D11Texture2D();

	if (pSrcTex == NULL || pDestTex == NULL)
		return E_FAIL;
	
	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC srcDesc;
	D3D11_TEXTURE2D_DESC destDesc;
	pSrcTex->GetDesc(&srcDesc);
	pDestTex->GetDesc(&destDesc);
	if (srcDesc.Width == destDesc.Width && srcDesc.Height == destDesc.Height && srcDesc.Format == destDesc.Format)
	{
		hr = KeyMutex11Acquire();
		pContext->CopyResource(pDestTex, pSrcTex);
		hr = KeyMutex11Release();
	}
	else
	{
		hr = KeyMutex11Acquire();
		hr = D3DX11LoadTextureFromTexture(pContext, pSrcTex, NULL, pDestTex);
		hr = KeyMutex11Release();
	}
	return hr;
}


HRESULT CDXTexture2D::GetShaderResourceView(DXGI_FORMAT fmt, UINT MostDetailedMip, UINT MipLevels, ID3D11ShaderResourceView** ppShaderResourceView)
{
	HRESULT hr = S_OK;
	D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc = {fmt, D3D11_SRV_DIMENSION_TEXTURE2D, {MostDetailedMip, MipLevels} };
	hr = GetShaderResourceView(&SRVDesc, ppShaderResourceView);	
	return hr;
}

HRESULT CDXTexture2D::GetUnorderedAccessView(DXGI_FORMAT fmt, UINT MipSlice, ID3D11UnorderedAccessView** ppUnorderAccessView)
{
	HRESULT hr = S_OK;
	D3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {fmt, D3D11_UAV_DIMENSION_TEXTURE2D, {MipSlice}};
	hr = GetUnorderedAccessView(&UAVDesc, ppUnorderAccessView);
	return hr;
}

HRESULT CDXTexture2D::GetRenderTargetView(DXGI_FORMAT fmt, UINT MipSlice, ID3D11RenderTargetView** ppRenderTargetView)
{
	HRESULT hr = S_OK;
	D3D11_RENDER_TARGET_VIEW_DESC RTVDesc = {fmt, D3D11_RTV_DIMENSION_TEXTURE2D, {MipSlice}};
	hr = GetRenderTargetView(&RTVDesc, ppRenderTargetView);
	return hr;
}

BOOL CDXTexture2D::IsKeyMutexShared()
{
	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC desc;
	hr = GetDesc(&desc);
	if (FAILED(hr))
		return FALSE;
	BOOL bKeyMutexShared = desc.MiscFlags &  D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
	return bKeyMutexShared;
}